package com.galudisu.handsonic.modules.system.service.impl;

import com.galudisu.handsonic.modules.system.dao.ResourceDao;
import com.galudisu.handsonic.modules.system.domain.Resource;
import com.galudisu.handsonic.modules.system.domain.User;
import com.galudisu.handsonic.modules.system.service.ResourceService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.permission.WildcardPermission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * @author Barudisshu
 */
@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    @Qualifier("resourceDao")
    private ResourceDao resourceDao;

    @Override
    public Resource createResource(Resource resource) {
        return resourceDao.save(resource);
    }

    @Override
    public Resource updateResource(Resource resource) {
        return resourceDao.save(resource);
    }

    @Override
    public void deleteResource(String resourceId) {
        resourceDao.delete(resourceId);
    }

    @Override
    public Resource findOne(String resourceId) {
        return resourceDao.findOne(resourceId);
    }

    @Override
    public List<Resource> findAll() {
        return resourceDao.findAll();
    }

    @Override
    public Set<String> findPermissions(Set<String> resourceIds) {
        return resourceDao.findPermissionsByResourceIds(resourceIds);
    }

    @Override
    public List<Resource> findMenus(Set<String> permissions) {
        List<Resource> allResources = findAll();
        List<Resource> menus = new ArrayList<Resource>();
        for (Resource resource : allResources) {
            if (StringUtils.isBlank(resource.getUrl())) {
                continue;
            }
            if (resource.getChilds().isEmpty()) {
                continue;
            }
            if (resource.getType() != Resource.ResourceType.menu) {
                continue;
            }
            if (!hasPermission(permissions, resource)) {
                continue;
            }
            menus.add(resource);
        }
        return menus;
    }

    @Override
    public List<String> findNamesByContain(Collection<String> resourceIds) {
        return resourceDao.findNamesByContain(resourceIds);
    }

    @Override
    public List<Resource> findMenuListByUser(User user) {
        return resourceDao.findMenuListByUser(user);
    }

    private boolean hasPermission(Set<String> permissions, Resource resource) {
        if (StringUtils.isEmpty(resource.getPermission())) {
            return true;
        }
        for (String permission : permissions) {
            WildcardPermission p1 = new WildcardPermission(permission);
            WildcardPermission p2 = new WildcardPermission(resource.getPermission());
            if (p1.implies(p2) || p2.implies(p1)) {
                return true;
            }
        }
        return false;
    }

}
